package org.game.module.datingbo.trigger;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.xiaoleilu.hutool.date.DateUnit;
import com.xiaoleilu.hutool.date.DateUtil;
import org.cfg.CityCfg;
import org.cfg.DatingRuleCfg;
import org.cfg.cache.CityCfgCache;
import org.cfg.cache.DatingRuleCfgCache;
import org.cfg.cache.DiscreteDataCfgCache;
import org.constant.DatingConstant;
import org.constant.DiscreteDataID;
import org.constant.DiscreteDataKey;
import org.constant.smallkey.PlayerDataSmallKey;
import org.game.constant.CityConstant;
import org.game.constant.DatingTypeConstant;
import org.game.db.bean.*;
import org.game.db.cache.CityCache;
import org.game.db.cache.RoleCache;
import org.game.module.datingbo.DatingBO;
import org.game.module.datingbo.DatingType;
import org.game.msgBuilder.DatingMsgBuilder;
import org.game.protobuf.s2c.S2CShareMsg;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 出游约会触发器
 * Created by fxf on 2018-3-14.
 */
@DatingType(DatingTypeConstant.DATING_TYPE_OUT)
public class OutDatingTrigger extends AbstractCityDatingTrigger {


    @Override
    public void triggerDating(Player player, Map<String, List<Integer>> timeFrame, Date now) {
        List<Integer> triggerFrame = timeFrame.get(DatingConstant.TRIGGER_TIME);
        if (alreadyTrigger(player, triggerFrame)) {
            return;
        }
        List<Integer> freeCityList = getFreeCityList(player);
        if (freeCityList.size() == 0) {
            return;
        }
        List<Integer> freeRoleList = getFreeRole(player);
        if (freeRoleList.size() == 0) {
            return;
        }
        Collections.shuffle(freeRoleList);
        List<DatingRuleCfg> datingRuleCfgList = getUsableOutDatingRuleCfg(freeRoleList, freeCityList);
        filtrateDating(player, datingRuleCfgList, timeFrame,now);
    }

    @Override
    public void refreshCityDating(Player player, List<CityDatingRecord> recordList, Date now) {
        int outDatingTime = ((Map<Integer, Integer>) DiscreteDataCfgCache.me().getData(DiscreteDataID.DATING, DiscreteDataKey.DATING_OUT_TIME)).get(DatingTypeConstant.DATING_TYPE_OUT);
        List<CityDatingRecord> outTimeRecordList = recordList.stream()
                .filter(record -> DateUtil.between(record.getCityDatingRecordProxy().getTriggerTime(), now, DateUnit.MINUTE) >= outDatingTime)
                .peek(record -> record.delete())
                .collect(Collectors.toList());
        if (outTimeRecordList != null && outTimeRecordList.size() > 0) {
            player.getPlayerProxy().sendMsg(DatingBO.updateCityDatingList, DatingMsgBuilder.buildCityDatingInfoList(S2CShareMsg.ChangeType.DELETE, outTimeRecordList));
        }
        refreshCity(player,outTimeRecordList);
    }

    private List<Integer> getFreeRole(Player player) {
        List<Role> all = RoleCache.me().getByPlayerId(player.getId());
        return all.stream()
                .filter(role -> !role.getRoleProxy().isCriticalPoint())
                .filter(role -> getReserveDateRecord(role) == null)//非预定约会状态
                .filter(role -> role.getWorkBuildingId() == 0)//非打工状态
                .map(role -> role.getCid())
                .collect(Collectors.toList());
    }

    private List<DatingRuleCfg> getUsableOutDatingRuleCfg(List<Integer> roleCidList, List<Integer> cityCidList) {
        List<DatingRuleCfg> all = DatingRuleCfgCache.me().getAll();
        return all.stream()
                .filter(cfg -> cfg.getType() == getDatingType())
                .filter(cfg -> cityCidList.contains(cfg.getEnterCondtionByType(DatingConstant.ENTER_CDTION_KEY_CITY_CID)))
                .filter(cfg -> cfg.getEnterCondition().get(DatingConstant.ENTER_CDTION_KEY_ROLE_CIDS) != null && roleCidList.containsAll((Collection<?>) cfg.getEnterCondition().get(DatingConstant.ENTER_CDTION_KEY_ROLE_CIDS)))
                .collect(Collectors.toList());
    }

    /**
     * 获取空闲的城市列表
     */
    private List<Integer> getFreeCityList(Player player){
        List<CityCfg> cityCfgList = CityCfgCache.me().getAll();
        List<Integer> cityCidList = Lists.newArrayList();
        for (CityCfg cityCfg : cityCfgList) {
            City city = CityCache.me().getByCidPlayerId(cityCfg.getId(),player.getId());
            if (cityCfg.getBuildType() == CityConstant.SPECIAL_ZONE && city == null){
                city = new City(0L,cityCfg.getId(),false,player.getId());
                city.insert();
                cityCidList.add(cityCfg.getId());
                continue;
            }
            if (city == null){
                continue;
            }
            if (!city.isInDating()){
                cityCidList.add(cityCfg.getId());
            }
        }
        return cityCidList;
    }
}
